export default class {
	constructor() {
		this.message = {
			'number': '$0只能是数字',
			'chinese': '$0只能是中文',
			'email': '$0格式不正确',
			'idcard': '$0格式不正确',
			'phone': '$0格式不正确',
			'require': '$0不能为空',
			'length': '$0长度只能是$1到$2个字符',
			'min': '$0至少$1个字符',
			'max': '$0不能超过$1个字符',
			'eq': '$0只能是$1',
			'neq': '$0不能为$1',
			'gt': '$0不能小于$1',
			'lt': '$0不能大于$1',
			'between': '$0值只能在$1到$2之间',
			'in': '$0只能取$n',
			'confirm': '$0与:1不一致'
		};
		this.test = {
			'number': /^-?\d*\.?\d+$/,
			'chinese': /^[\u4e00-\u9fa5]+$/,
			'email': /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/,
			'idcard': /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
			'phone': /^[1][3-9][0-9]{9}$/,
			'require': function (v) { return (v !== null && v != undefined && v !== ''); },
			'length': function (v, m, n) { return !(('' + v).length < m || ('' + v).length > n); },
			'min': function (v, l) { return ('' + v).length >= l; },
			'max': function (v, l) { return ('' + v).length <= l; },
			'eq': function (v, m) { return v == m; },
			'neq': function (v, m) { return v != m; },
			'gt': function (v, m) { return v > m; },
			'lt': function (v, m) { return v < m; },
			'between': function (v, m, n) {
				if (isNaN(v)) return false;
				return v > m && v < n;
			},
			'in': function () {
				for (let i = 1, len = arguments.length; i < len; i++)
					if (arguments[0] == arguments[i])
						return true;
				return false;
			},
			'confirm': function (v, m) {
				return v == this.data[m];
			}
		};
	}
	/**
	 * 添加或修改规则
	 * @param  name 规则名称
	 * @param  rule 规则内容（函数或正则）
	 * @param  msg  消息
	 * @return      this
	 */
	rule(name, rule, msg) {
		this.test[name] = rule ? rule : this.test[name];
		this.message[name] = msg ? msg : this.message[name];
		return this;
	}
	parse(rule) {
		var s = rule.split('!'), s2 = s[0].split(':');
		return { name: s2[0], args: s2.length == 2 ? s2[1].split(',') : [], msg: s.length == 2 ? s[1] : (this.message[s2[0]] ? this.message[s2[0]] : '$0格式不对') };
	}
	format(rule) {
		var data = {};
		for (let i in rule) {
			let item = rule[i].split('|'), t = { name: i, rule: [] };
			while (item.length > 0) {
				var j = item.shift();
				if (j[0] == '@') t.name = j.substr(1);
				else t.rule.push(this.parse(j));
			}
			data[i] = t;
		}
		return data;
	}
	check(rule, data, all) {
		var result = {};
		if (typeof (rule) == 'string' && typeof (data) == 'string') {
			rule = { 'field': rule };
			data = { 'field': data };
		}
		rule = this.format(rule);
		this.data = data;
		for (let i in rule) {
			let items = rule[i].rule;
			for (let j in items) {
				var fn = this.test[items[j].name];
				if (!fn) continue;
				var test = typeof (fn) == "function" ? fn.apply(this, [data[i], ...items[j].args]) : fn.test(data[i]);
				if (test !== true) {
					var tpl = [rule[i].name, ...items[j].args], msg = items[j].msg.replace(/[$:]{1}[\dn]*/g, function (v) {
						if (v[0] == ':') return rule[tpl[v.substr(1)]].name;
						if (v == '$n') return items[j].args.join(',');
						return tpl[v.substr(1)];
					});
					if (all) result[i] = msg;
					else return msg;
				}
			}
		}
		if (JSON.stringify(result) != '{}') return result;
		else return true;
	}
};